#include "lsb/lsb_embedding_engine.h"

const std::string CLSBEmbeddingEngine::sIniSectionName("LSB");

const int CLSBEmbeddingEngine::sNumRequiredSamples(1);
const NAudioFormats::ESamplesFormat CLSBEmbeddingEngine::sSamplesFormat(NAudioFormats::ORIGINAL);

CLSBEmbeddingEngine::CLSBEmbeddingEngine(IBitSource* pBitSource) : 
	mBitSource(pBitSource)
{

}

CLSBEmbeddingEngine::~CLSBEmbeddingEngine()
{

}

std::string CLSBEmbeddingEngine::getIniSectionName() const
{
	return CLSBEmbeddingEngine::sIniSectionName;
}

int CLSBEmbeddingEngine::embedIntoSamples(int8_t* pSamples, unsigned int pCount, unsigned int pLeak)
{
	uint8_t lSample(pSamples[0]);
	int lReturn(embedIntoSamples(&lSample, pCount, pLeak));

	pSamples[0] = lSample;

	return lReturn;
}

int CLSBEmbeddingEngine::embedIntoSamples(uint8_t* pSamples, unsigned int pCount, unsigned int pLeak)
{
	bool lSet(false);
	int lReturn = mBitSource->getBit(lSet);

	if (lSet) {
		pSamples[0] |= 0x01;
	} else {
		pSamples[0] &= 0xFE;
	}

	return lReturn; 
}

int CLSBEmbeddingEngine::embedIntoSamples(int16_t* pSamples, unsigned int pCount, unsigned int pLeak)
{
	uint8_t lSample(pSamples[0] & 0x00FF);
	int lReturn(embedIntoSamples(&lSample, pCount, pLeak));

	pSamples[0] &= 0xFF00;
	pSamples[0] += lSample;

	return lReturn;
}

int CLSBEmbeddingEngine::embedIntoSamples(uint16_t* pSamples, unsigned int pCount, unsigned int pLeak)
{
	uint8_t lSample(pSamples[0] & 0x00FF);
	int lReturn(embedIntoSamples(&lSample, pCount, pLeak));

	pSamples[0] &= 0xFF00;
	pSamples[0] += lSample;

	return lReturn;
}

int CLSBEmbeddingEngine::extractFromSamples(int8_t* pSamples, unsigned int pCount, unsigned int pLeak, unsigned int pInBuffer)
{
	uint8_t lSample(pSamples[0]);

	return extractFromSamples(&lSample, pCount, pLeak, pInBuffer);
}

int CLSBEmbeddingEngine::extractFromSamples(uint8_t* pSamples, unsigned int pCount, unsigned int pLeak, unsigned int pInBuffer)
{
	bool lValue(false);

	if ((pSamples[0] & 0x01) == 0x01) {
		lValue = true;
	}

	mBitSource->putBit(lValue);
	return 0;
}

int CLSBEmbeddingEngine::extractFromSamples(int16_t* pSamples, unsigned int pCount, unsigned int pLeak, unsigned int pInBuffer)
{
	uint8_t lSample(pSamples[0] & 0x00FF);

	return extractFromSamples(&lSample, pCount, pLeak, pInBuffer);
}

int CLSBEmbeddingEngine::extractFromSamples(uint16_t* pSamples, unsigned int pCount, unsigned int pLeak, unsigned int pInBuffer)
{
	uint8_t lSample(pSamples[0] & 0x00FF);

	return extractFromSamples(&lSample, pCount, pLeak, pInBuffer);
}

